package librairies.dictionnaire.dico;

import librairies.arborescence.arbre.ArbreDC;
import librairies.arborescence.interfaces.IArbre;
import librairies.dictionnaire.interfaces.IDictionnaire;
import librairies.dictionnaire.interfaces.IDonneeDico;
import librairies.liste.interfaces.IListe;
import librairies.liste.list.ListeDC;

/**
 * dictionnaire sous forme d'arbre.
 * 
 * @author mlozach
 * @param <E> type de l'elements dans l'arbre
 */
public class DicoArbre<E extends IDonneeDico<E>> implements IDictionnaire<E> 
{
	private IArbre<E> arbre;
	
	/**
	 * constructeur par defaut.
	 */
	public DicoArbre() 
	{
		this.arbre = new ArbreDC<E>(null);
	}

	/**
	 * constructeur par recopie.
	 * @param file la liste d'entree.
	 */
	public DicoArbre(IListe<E> file)
	{
		this();
		this.addWords(file);
	} 

	/**
	 * parcourt récursivement l'arbre en reconstituant des mots qui commencent par prefix.
	 * @param a l'arbre.
	 * @param prefix le prefix.
	 * @return la liste de mot trouver.
	 */
	private IListe<E> genListe(IArbre<E> a, E prefix) 
	{
		System.out.println("reste a faire");
		System.out.flush();		
		//TODO a voir plus tard
		return null;
	}
	
	/**
	 * parcourt récursivement l'arbre en ajoutant lettre par lettre la chaine de caractere.
	 * @param s le mot a mettre.
	 * @param a l'arbre.
	 */
	private void addWord(E s, IArbre<E> a) 
	{
		System.out.println("reste a faire");
		System.out.flush();
		//TODO a voir plus tard
	}
	
	/**
	 * parcourt récursivement l'arbre en mémorisant dans le couple (pereDuFilsACouper, filsACouper) la branche à couper.
	 * Si la chaine apparaît dans le dictionnaire, alors la branche mémorisée est supprimée.
	 * @param s le mot.
	 * @param a l'arbre.
	 * @param pereDuFilsACouper sous arbre.
	 * @param filsACouper sous arbre.
	 */
	private void cutWord(E s, IArbre<E> a, IArbre<E> pereDuFilsACouper, int filsACouper) 
	{
		System.out.println("reste a faire");
		System.out.flush();
		//TODO a voir plus tard
	}
	
	/**
	 * parcourt récursivement l'arbre en comptant le nombre de points.
	 * @param a l arbre.
	 * @return nombre de point.
	 */
	private int nbPoints (IArbre<E> a) 
	{
		System.out.println("reste a faire");
		System.out.flush();
		//TODO a voir plus tard
		return 0;
	}

	/**
	 *  parcourt récursivement l'arbre sur un chemin correspondant au mot.
	 * @param s le mot.
	 * @param a l'arbre.
	 * @return l'arbre du mot ou null.
	 */
	private IArbre<E> sousArbre (E s, IArbre<E> a) 
	{
		System.out.println("reste a faire");
		System.out.flush();
		//TODO a voir plus tard
		return null;
	}
	
	@Override
	public IDictionnaire<E> addWords(IListe<E> words) 
	{
		for(int i = 0; i < words.size(); i++)
		{ 
			addWord(words.get(i), this.arbre);  
		}
		return this;
	}

	@Override
	public IDictionnaire<E> cutWords(IListe<E> words) 
	{
		for(int i = 0; i < words.size(); i++)
		{
			cutWord(words.get(i), this.arbre, null, -1);  
		}
		return this;
	}

	@Override
	public int size() 
	{
		return nbPoints(this.arbre);
	}
	
	@Override
	public boolean exists(E word) 
	{
		return sousArbre(word, this.arbre)!=null;
	}

	@Override
	public IListe<E> commonPrefix(E prefix) 
	{
		IArbre<E> a = sousArbre(prefix, this.arbre);
		IListe<E> sufix = (a==null ? new ListeDC<E>() : genListe(a, null));
		IListe<E> res = new ListeDC<E>();
		for(int i = 0; i < sufix.size(); i++)
		{
			//E tmp = (E) prefix.addition(sufix.get(i)); //TODO j'ai un doute
			//res.add(tmp);
		}
		return res;
	}

	@Override
	public E getObjet(String word)
	{
		//TODO a voir plus tard
		return null;
	}
	
	@Override
	public IListe<E> contains(E prefix) 
	{
		//TODO a voir plus tard
		return null;
	}
	
	public IArbre<E> getArbre() {return arbre;}

	/**
	 * methode Object
	 */
	public String toString() 
	{
		String res="";
		IListe<E> words = genListe(this.arbre, null);
		for(int i = 0; i < words.size(); i++)
		{
			res += words.get(i).toString()+"\n";
		}
		return res;
	}
}